﻿using System;
using System.Linq;
using System.Linq.Expressions;

using Sustainalytics.Entities;
using Sustainalytics.Utils;

namespace Sustainalytics.Portfolios.BL.Model
{
    public class PortfolioFilter
    {
        public Guid? PortfolioId { get; set; }
        public string Name { get; set; }
        public PortfolioSharingStatus? SharingStatus { get; set; }
        public PortfolioTypes? PortfolioType { get; set; }
        public Guid AddedByUserId { get; set; }
        public bool IsNameEqual { get; set; }
        public Guid? AccountId { get; set; }
        public bool? IsMyPortfolio { get; set; }

        public Expression<Func<Portfolio, bool>> GetFilterExpression()
        {
            // todo: should be taken care when because Mongo does not support expression invocation
            // therfor keep the same lambda parameter everywhere in the function
            Expression<Func<Portfolio, bool>> query = p => true;

            if (AccountId != null)
            {
                query = query.And(p => p.AccountIds.Contains(AccountId.Value));
            }

            if (PortfolioType.GetValueOrDefault() == PortfolioTypes.Custom)
            {
                query = query.And(p => (!p.IsAutomatic));
            }

            if (PortfolioType.GetValueOrDefault() == PortfolioTypes.System)
            {
                query = query.And(p => p.IsAutomatic);
            }

            if (SharingStatus != null && SharingStatus != PortfolioSharingStatus.All)
            {
                query = query.And(p => p.SharingStatus == SharingStatus.Value);
            }

            if ((PortfolioType == PortfolioTypes.Custom) && (SharingStatus != null) && (SharingStatus.Value != PortfolioSharingStatus.Shared))
            {                
                query = query.And(p => p.AddedByUserId == AddedByUserId);
            }

            if ((PortfolioType == PortfolioTypes.All) && (SharingStatus != null) && (SharingStatus.Value == PortfolioSharingStatus.All))
            {
                query = query.And(
                    p => (p.SharingStatus == PortfolioSharingStatus.Private && p.AddedByUserId == AddedByUserId) || 
                    ((p.IsAutomatic && p.IsReadonly) || 
                    (p.SharingStatus == PortfolioSharingStatus.Shared)));
            }

            if ((PortfolioType == PortfolioTypes.System) && (SharingStatus != null) && (SharingStatus.Value == PortfolioSharingStatus.All))
            {
                query = query.And(p => (p.IsAutomatic && p.IsReadonly) || (p.AddedByUserId == AddedByUserId));
            }

            if ((PortfolioType == PortfolioTypes.System) && (SharingStatus != null) && (SharingStatus.Value == PortfolioSharingStatus.Shared))
            {
                query = query.And(p => (p.IsAutomatic && p.IsReadonly));
            }

            if ((PortfolioType == PortfolioTypes.System) && (SharingStatus != null) && (SharingStatus.Value == PortfolioSharingStatus.Private))
            {
                query = query.And(p => p.AddedByUserId == AddedByUserId);
            }

            if (!string.IsNullOrWhiteSpace(Name))
            {
                query = IsNameEqual ? query.And(p => p.Name == Name) : query.And(p => p.Name.ToLowerInvariant().Contains(Name.ToLowerInvariant()));
            }

            if (PortfolioId != null)
            {
                query = query.And(p => p.Id == PortfolioId);
            }

            return query;
        }
    }
}
